//package com.ibm.risk.irmp.common.auth.oauth2;
//
//import com.ibm.risk.irmp.common.auth.oauth2.welink.OAuth2Configuration;
//import com.ibm.risk.irmp.common.auth.sso.SSOProcessor;
//import com.nimbusds.oauth2.sdk.ErrorObject;
//import com.nimbusds.openid.connect.sdk.UserInfoErrorResponse;
//import lombok.extern.slf4j.Slf4j;
//import net.minidev.json.JSONObject;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.core.ParameterizedTypeReference;
//import org.springframework.http.HttpHeaders;
//import org.springframework.http.HttpStatusCode;
//import org.springframework.http.MediaType;
//import org.springframework.http.server.reactive.ServerHttpRequest;
//import org.springframework.http.server.reactive.ServerHttpResponse;
//import org.springframework.util.StringUtils;
//import org.springframework.web.reactive.function.client.ClientResponse;
//import org.springframework.web.reactive.function.client.WebClient;
//import reactor.core.publisher.Mono;
//
//import java.util.Map;
//
//@Slf4j
//public class DefaultReactiveOAuth2SSOProcessor implements SSOReactiveProcessor {
//
//    public static final String TOKEN = "access_token";
//
//    private static final String FORM = "form";
//    private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response";
//
//    private static final String MISSING_USER_INFO_URI_ERROR_CODE = "missing_user_info_uri";
//
//    private static final String MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE = "missing_user_name_attribute";
//
//    private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP = new ParameterizedTypeReference<Map<String, Object>>() {
//    };
//
//    private static final ParameterizedTypeReference<Map<String, String>> STRING_STRING_MAP = new ParameterizedTypeReference<Map<String, String>>() {
//    };
//
//    private WebClient webClient = WebClient.create();
//
//
//    @Autowired
//    private OAuth2Configuration configuration;
//
//    @Override
//    public void processSSO(ServerHttpRequest request, ServerHttpResponse response) {
//
//        getTokenFromCode(request).subscribe(
//                t -> getUserId(request, t).subscribe(
//                        userId -> {
//                            log.info("UserId: {}", userId);
//                            //response.addCookie("");
//                        }
//                )
//        );
//    }
//
//    private Mono<String> getUserId(ServerHttpRequest request, String t) {
//        WebClient.RequestHeadersSpec<?> requestHeadersSpec = getUserIdRequestHeaderSpec(request, t);
//        return getRestResponse(request, requestHeadersSpec).map((map) -> {
//            Object userId = map.get(configuration.getUserNameAttribute());
//            log.info("userId: {}", userId);
//            return (String) userId;
//        }).onErrorMap((e) -> {
//            log.error("Error:", e);
//            throw new RuntimeException(e);
//        });
//    }
//
//    protected  Mono<String> getTokenFromCode(ServerHttpRequest request) {
//        String code = request.getQueryParams().getFirst("code");
//        WebClient.RequestHeadersSpec<?> requestHeaderSpec = getTokenRequestHeaderSpec(request, code);
//        return getRestResponse(request, requestHeaderSpec).map((map) -> {
//            String token = (String)map.get(TOKEN);
//            log.info("Token map: {}", map);
//            return token;
//        });
//
//    }
//    protected Mono<Map<String, Object>> getRestResponse(ServerHttpRequest request, WebClient.RequestHeadersSpec<?> requestHeadersSpec) {
//        Mono<Map<String, Object>> respAttrs = requestHeadersSpec.retrieve()
//                .onStatus(HttpStatusCode::isError, (response) ->
//                        parse(response)
//                                .map((userInfoErrorResponse) -> {
//                                    String description = userInfoErrorResponse.getErrorObject().getDescription();
//                                    String oauth2Error = description;
//                                    throw new RuntimeException(oauth2Error);
//                                })
//                )
//                .bodyToMono(STRING_OBJECT_MAP);
//        return respAttrs;
//    }
//    private WebClient.RequestHeadersSpec<?> getUserIdRequestHeaderSpec(ServerHttpRequest request, String token) {
//        if (!StringUtils.hasText(token)) {
//            throw new RuntimeException("No token value found.");
//        }
//        if (FORM.equals(configuration.getAuthenticationMethod())) {
//            // @formatter:off
//            return this.webClient.post()
//                    .uri(configuration.getUserInfoUri())
//                    .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
//                    .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
//                    .bodyValue("access_token=" + token);
//            // @formatter:on
//        }
//        // @formatter:off
//        return this.webClient.get()
//                .uri(configuration.getUserInfoUri())
//                .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
//                .headers((headers) -> setToken(headers, token));
//        // @formatter:on
//    }
//    private WebClient.RequestHeadersSpec<?> getTokenRequestHeaderSpec(ServerHttpRequest request, String code) {
//        if (!StringUtils.hasText(code)) {
//            throw new RuntimeException("No code value found.");
//        }
//        // @formatter:off
//        return this.webClient.get()
//                .uri(configuration.getTokenUri() + "&code=" + code)
//                .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
//        // @formatter:on
//    }
//    protected void setToken(HttpHeaders headers, String token) {
//        headers.setBearerAuth(token);
//    }
//    private static Mono<UserInfoErrorResponse> parse(ClientResponse httpResponse) {
//        String wwwAuth = httpResponse.headers().asHttpHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE);
//        if (StringUtils.hasLength(wwwAuth)) {
//            // Bearer token error?
//            return Mono.fromCallable(() -> UserInfoErrorResponse.parse(wwwAuth));
//        }
//        // Other error?
//        return httpResponse.bodyToMono(STRING_STRING_MAP)
//                .map((body) -> new UserInfoErrorResponse(ErrorObject.parse(new JSONObject(body))));
//    }
//    @Override
//    public void logout(ServerHttpRequest request, ServerHttpResponse response) {
//
//    }
//}
